Helper.using('py.Figures', function (ns) {

    ns.Circle = function (params){
        ns.Figure.call(this, params);
        ns.setType('Circle');
    }
    ns.Circle = function (params) {
        ns.Figure.call(this, params);
        ns.setType('Circle');

        var pi = Math.PI,
            visual = new Kinetic.Circle({
                strokeWidth:2,
                stroke:'black',
                draggable:false
            });

        this.getCenter = Helper.abstractMethod();
        this.getRadius = Helper.abstractMethod();

        this.getArea = function () {
            var r = this.getRadius();
            return r * r * pi;
        };

        this.getPerimeter = function () {
            var r = this.getRadius();
            return 2 * r * pi;
        };

        this.getBound = function () {
            var c = this.getCenter().getPosition(), r = this.getRadius(), d = 2 * r;
            return new Bound({x:c.x + r, y:c.y - r, w:d, h:d});
        };

        this.update = function (viewPort) {
            var c = viewPort.getPixelPoint(this.getCenter().getPosition()),
                r = viewPort.getPixelLength(this.getRadius());

            visual.setX(c.x);
            visual.setY(c.y);
            visual.setRadius(r);
        };

        this.drawFunc = function(viewPort) {
            this.update(viewPort);
            this.layer().draw();
        };

        this.visual(visual);
    };

    ns.Circle2Point = function(params) {
        ns.Circle.call(this, params);
        this.setType('Circle2Point');

        var empty = new ns.PointXY;

        params = Helper.extend({
            center : empty,
            point : empty
        }, params);

        this.getCenter = function() {
            return params.center;
        };
        this.getRadius = function() {
            return ns.Point.distance(params.center, params.point);
        };

        this.setCenter = function(center) {
            params.center = center;
        };

        this.setPoint = function(point) {
            params.point = point;
        };
    };

    // params = {points : array[Point]}
    ns.Circle3Point = function(params) {
        ns.Circle.call(this, params);
        this.setType('Circle3Point');

        params = Helper.extend({
            points : []
        }, params);

        var center = new ns.PointXY;

        this.formed = function () {
            return params.points.length == 3;
        };

        this.getCenter = function() {
            var positions = [];
            params.points.forEach( function(p) {
                positions.push(p.getPosition());
            });

            var c = py.Math.CircleUtils.getCircleCenterFromPoints(positions);
            center.setX(c.x);
            center.setY(c.y);
            return center;
        };

        this.getRadius = function() {
            return py.Figures.Point.distance(this.getCenter(), params.points[0]);
        };

        this.setPoints = function(points) {
            params.points = points;
        };

        this.setPoint = function(index, point) {
            params.points[index] = point;
        };

    };

    // params = {center, radius}
    ns.CircleWithRadius = function(params) {
        ns.Circle.call(this,params);
        this.setType('CircleWithRadius');

        var empty = new ns.PointXY();

        params = Helper.extend(
            {center : empty, radius : 0},
            params);

        this.getCenter = function() {
            return params.center;
        }

        this.getRadius = function() {
            return params.radius;
        }

    };

});